Next: Function Cells, Previous: Anonymous Functions, Up: Functions [Contents][Index]
Functions defined using defun have a hard-coded
set of assumptions about the types and expected values of their
arguments. For example, a function that was designed to handle
values of its argument that are either numbers or lists of
numbers will fail or signal an error if called with a value of
any other type, such as a vector or a string. This happens
because the implementation of the function is not prepared to
deal with types other than those assumed during the design.
By contrast, object-oriented programs use polymorphic functions: a set of specialized functions having the same name, each one of which was written for a certain specific set of argument types. Which of the functions is actually called is decided at run time based on the types of the actual arguments.
Emacs provides support for polymorphism. Like other Lisp environments, notably Common Lisp and its Common Lisp Object System (CLOS), this support is based on generic functions. The Emacs generic functions closely follow CLOS, including use of similar names, so if you have experience with CLOS, the rest of this section will sound very familiar.
A generic function specifies an abstract operation, by
defining its name and list of arguments, but (usually) no
implementation. The actual implementation for several specific
classes of arguments is provided by methods, which
should be defined separately. Each method that implements a
generic function has the same name as the generic function, but
the method’s definition indicates what kinds of arguments
it can handle by specializing the arguments defined by
the generic function. These argument specializers can be
more or less specific; for example, a string type is
more specific than a more general type, such as
sequence.
Note that, unlike in message-based OO languages, such as C++ and Simula, methods that implement generic functions don’t belong to a class, they belong to the generic function they implement.
When a generic function is invoked, it selects the applicable methods by comparing the actual arguments passed by the caller with the argument specializers of each method. A method is applicable if the actual arguments of the call are compatible with the method’s specializers. If more than one method is applicable, they are combined using certain rules, described below, and the combination then handles the call.
This macro defines a generic function with the specified
name and arguments. If body
is present, it provides the default implementation. If
documentation is present (it should always be), it
specifies the documentation string for the generic function,
in the form (:documentation
docstring). The optional
options-and-methods can be one of the following
forms:
(declare declarations)A declare form, as described in Declare Form.
(:argument-precedence-order &rest
args)This form affects the sorting order for combining applicable methods. Normally, when two methods are compared during combination, method arguments are examined left to right, and the first method whose argument specializer is more specific will come before the other one. The order defined by this form overrides that, and the arguments are examined according to their order in this form, and not left to right.
(:method [qualifiers…] args
&rest body)This form defines a method like
cl-defmethod does.
This macro defines a particular implementation for the
generic function called name. The implementation
code is given by body. If present,
docstring is the documentation string for the
method. The arguments list, which must be
identical in all the methods that implement a generic
function, and must match the argument list of that function,
provides argument specializers of the form
(arg spec), where
arg is the argument name as specified in the
cl-defgeneric call, and spec is one
of the following specializer forms:
typeThis specializer requires the argument to be of the given type, one of the types from the type hierarchy described below.
(eql object)This specializer requires the argument be
eql to the given object.
(head object)The argument must be a cons cell whose
car is eql to
object.
struct-tagThe argument must be an instance of a class named
struct-tag defined with
cl-defstruct (see
Structures in Common Lisp Extensions for GNU
Emacs Lisp), or of one of its parent classes.
Alternatively, the argument specializer can be of the form
&context (expr spec),
in which case the value of expr must be compatible
with the specializer provided by spec;
spec can be any of the forms described above. In
other words, this form of specializer uses the value of
expr instead of arguments for the decision whether
the method is applicable. For example, &context
(overwrite-mode (eql t)) will make the method
compatible only when overwrite-mode is turned
on.
The type specializer, (arg
type), can specify one of the system
types in the following list. When a parent type is
specified, an argument whose type is any of its more specific
child types, as well as grand-children, grand-grand-children,
etc. will also be compatible.
integerParent type: number.
numbernullParent type: symbol
symbolstringParent type: array.
arrayParent type: sequence.
consParent type: list.
listParent type: sequence.
markeroverlayfloatParent type: number.
window-configurationprocesswindowsubrcompiled-functionbufferchar-tableParent type: array.
bool-vectorParent type: array.
vectorParent type: array.
framehash-tablefont-specfont-entityfont-objectThe optional qualifier allows combining several applicable methods. If it is not present, the defined method is a primary method, responsible for providing the primary implementation of the generic function for the specialized arguments. You can also define auxiliary methods, by using one of the following values as qualifier:
:beforeThis auxiliary method will run before the primary
method. More accurately, all the :before
methods will run before the primary, in the
most-specific-first order.
:afterThis auxiliary method will run after the primary method. More accurately, all such methods will run after the primary, in the most-specific-last order.
:aroundThis auxiliary method will run instead of the
primary method. The most specific of such methods will be
run before any other method. Such methods normally use
cl-call-next-method, described below, to
invoke the other auxiliary or primary methods.
:extra stringThis allows you to add more methods, distinguished by string, for the same specializers and qualifiers.
Each time a generic function is called, it builds the effective method which will handle this invocation by combining the applicable methods defined for the function. The process of finding the applicable methods and producing the effective method is called dispatch. The applicable methods are those all of whose specializers are compatible with the actual arguments of the call. Since all of the arguments must be compatible with the specializers, they all determine whether a method is applicable. Methods that explicitly specialize more than one argument are called multiple-dispatch methods.
The applicable methods are sorted into the order in which they
will be combined. The method whose left-most argument specializer
is the most specific one will come first in the order.
(Specifying :argument-precedence-order as part of
cl-defmethod overrides that, as described above.) If
the method body calls cl-call-next-method, the next
most-specific method will run. If there are applicable
:around methods, the most-specific of them will run
first; it should call cl-call-next-method to run any
of the less specific :around methods. Next, the
:before methods run in the order of their
specificity, followed by the primary method, and lastly the
:after methods in the reverse order of their
specificity.
When invoked from within the lexical body of a primary or
an :around auxiliary method, call the next
applicable method for the same generic function. Normally, it
is called with no arguments, which means to call the next
applicable method with the same arguments that the calling
method was invoked. Otherwise, the specified arguments are
used instead.
This function, when called from within the lexical body of
a primary or an :around auxiliary method,
returns non-nil if there is a next method to
call.
Next: Function Cells, Previous: Anonymous Functions, Up: Functions [Contents][Index]